package com.bosicloud.cmb.ibp.api.manager.util;

import com.alibaba.fastjson.JSONObject;
import io.swagger.models.*;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.Property;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;


@Slf4j
public class ModelProcessor {

    private final Swagger swagger;

    private final PropertyProcessor propertyProcessor;

    public ModelProcessor(Swagger swagger) {
        this.swagger = swagger;
        this.propertyProcessor = new PropertyProcessor(swagger);

    }

    public JSONObject processModel(Model model) {
        if (Objects.isNull(model)) {
            return new JSONObject();
        }
        if (model instanceof RefModel) {
            return processRefModel((RefModel) model);
        } else if (model instanceof ArrayModel) {
            return processArrayModel((ArrayModel) model);
        } else if (model instanceof ComposedModel) {
            return processComposedModel((ComposedModel) model);
        } else if (model instanceof ModelImpl) {
            return processModelImpl((ModelImpl) model);
        }
        return new JSONObject();
    }

    private JSONObject processModelImpl(ModelImpl modelImpl) {
        JSONObject jsonObject = new JSONObject();
        final Map<String, Property> properties = modelImpl.getProperties();
        if (Objects.isNull(properties)) {
            return jsonObject;
        }
        for (Map.Entry<String, Property> entry : properties.entrySet()) {
            JSONObject jsonResult = propertyProcessor.processProperty(entry.getValue(), new JSONObject(),
                    entry.getKey(), entry.getValue().getType());
            jsonObject.putAll(jsonResult);
        }
        return jsonObject;

    }

    private JSONObject processComposedModel(ComposedModel composedModel) {
        JSONObject jsonObject = new JSONObject();
        processModel(composedModel.getParent());
        processModel(composedModel.getChild());
        final List<RefModel> interfaces = composedModel.getInterfaces();
        if (interfaces != null) {
            for (RefModel model : interfaces) {
                jsonObject.putAll(processRefModel(model));
            }
        }
        return jsonObject;
    }

    private JSONObject processArrayModel(ArrayModel arrayModel) {
        JSONObject jsonObject = new JSONObject();
        final Property items = arrayModel.getItems();
        if (Objects.nonNull(items)) {
            JSONObject jsonResult = propertyProcessor.processProperty(items, new JSONObject(),
                    items.getName(), ArrayProperty.TYPE);
            jsonObject.putAll(jsonResult);
        }
        return jsonObject;
    }


    private JSONObject processRefModel(RefModel refModel) {
        JSONObject jsonObject = new JSONObject();
        Optional<Model> optionalModel = Optional.ofNullable(swagger.getDefinitions().get(refModel.getSimpleRef()));
        if (optionalModel.isPresent()) {
            Optional<Map<String, Property>> mapOptional = Optional.ofNullable(optionalModel.get().getProperties());
            if (mapOptional.isPresent()) {
                for (Map.Entry<String, Property> entry : mapOptional.get().entrySet()) {
                    JSONObject jsonResult = propertyProcessor.processProperty(entry.getValue(), new JSONObject(),
                            entry.getKey(), entry.getValue().getType());
                    jsonObject.putAll(jsonResult);
                }
            }
        }
        return jsonObject;
    }


}
